package core

import (
	"demo-2025/demo01/global"
	"github.com/robfig/cron/v3"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"log"
	"os"
)

// 创建 cron 实例，全局挂载，便于统一管理
// 创建并初始化 cron 实例，挂载到全局变量，保证全局只有一个调度器实例。

// InitCron 初始化 cron 实例，支持秒级调度
func InitCron() *cron.Cron {
	// 使用秒级时间配置
	return cron.New(cron.WithSeconds())
}

// InitLog 参考：https://juejin.cn/post/7313979344561242162
func InitLog() *zap.Logger {
	//return zap.NewExample()
	logger, _ := zap.NewDevelopment()
	defer func(logger *zap.Logger) {
		err := logger.Sync() // 刷新 buffer，保证日志最终会被输出
		if err != nil {
			log.Fatalln("程序退出前调用 日志记录器.Sync() 方法失败：" + err.Error())
		}
	}(logger)
	return logger
}

// InitSugaredLog 参考：https://juejin.cn/post/7313979344561242162
func InitSugaredLog() *zap.SugaredLogger {
	//return zap.NewExample()
	logger, _ := zap.NewDevelopment()
	defer func(logger *zap.Logger) {
		err := logger.Sync() // 刷新 buffer，保证日志最终会被输出
		if err != nil {
			log.Fatalln("程序退出前调用 日志记录器.Sync() 方法失败：" + err.Error())
		}
	}(logger)
	// 通过 logger.Sugar() 方法可以将一个 Logger 对象转换成一个 SugaredLogger 对象
	return logger.Sugar()
}

func InitLogger() {
	//获取编码器
	encoder := getEncoder()

	// https://juejin.cn/post/7313979344561242162#heading-7
	//对日志级别进行判断、分类
	highPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool { //error级别
		return lev >= zap.ErrorLevel
	})
	lowPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool { //info和debug级别,debug级别是最低的
		return lev < zap.ErrorLevel && lev >= zap.DebugLevel
	})
	//info文件WriteSyncer
	infoFileWriteSyncer := getInfoWriterSyncer()
	//error文件WriteSyncer
	errorFileWriteSyncer := getErrorWriterSyncer()
	//同时输出到控制台 和 指定的日志文件中
	infoFileCore := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(infoFileWriteSyncer, zapcore.AddSync(os.Stdout)), lowPriority)
	errorFileCore := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(errorFileWriteSyncer, zapcore.AddSync(os.Stdout)), highPriority)
	//将infocore 和 errcore 加入core切片
	var coreArr []zapcore.Core
	coreArr = append(coreArr, infoFileCore)
	coreArr = append(coreArr, errorFileCore)
	//生成logger
	logger := zap.New(zapcore.NewTee(coreArr...), zap.AddCaller()) //zap.AddCaller() 显示文件名 和 行号
	global.GVA_LOG = logger
	global.GVA_SUGARED_LOG = logger.Sugar()

	//writerSyncer := getWriterSyncer()
	//这里我们使用zapcore.NewMultiWriteSyncer()实现同时输出到多个对象中
	// os.Stdout 为控制台输出
	//core := zapcore.NewCore(encoder, writerSyncer, zap.DebugLevel)
	// //AddSync将io.Writer转换成WriteSyncer的类型
	//core := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(writerSyncer, zapcore.AddSync(os.Stdout)), zap.DebugLevel)

	//global.GVA_LOG = zap.New(core, zap.AddCaller()) //zap.AddCaller() 显示文件名 和 行号
	//global.GVA_SUGARED_LOG = global.GVA_LOG.Sugar()
}

func getEncoder() zapcore.Encoder {
	//return zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
	encoderConfig := zap.NewProductionEncoderConfig()
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
	return zapcore.NewConsoleEncoder(encoderConfig)
}

// core 三个参数之  日志输出路径
func getWriterSyncer() zapcore.WriteSyncer {
	//file, _ := os.Create("./zaplogs/log.log") //指定日志输出文件位置
	//return zapcore.AddSync(file)

	//引入第三方库 Lumberjack 加入日志切割功能
	lumberWriteSyncer := &lumberjack.Logger{
		Filename:   "./zaplogs/log.log",
		MaxSize:    10, // megabytes
		MaxBackups: 100,
		MaxAge:     28,    // days
		Compress:   false, //Compress确定是否应该使用gzip压缩已旋转的日志文件。默认值是不执行压缩。
	}
	return zapcore.AddSync(lumberWriteSyncer)
}

// 记录error以下日志级别的文件
func getInfoWriterSyncer() zapcore.WriteSyncer {
	//file, _ := os.Create("./server/zaplog/log.log")
	// 或者将上面的NewMultiWriteSyncer放到这里来，进行返回
	//return zapcore.AddSync(file)

	//引入第三方库 Lumberjack 加入日志切割功能
	infoLumberIO := &lumberjack.Logger{
		Filename:   "./zaplogs/info.log",
		MaxSize:    10, // megabytes
		MaxBackups: 100,
		MaxAge:     28,    // days
		Compress:   false, //Compress确定是否应该使用gzip压缩已旋转的日志文件。默认值是不执行压缩。
	}
	return zapcore.AddSync(infoLumberIO)
}

// 记录error及以上日志级别的文件
func getErrorWriterSyncer() zapcore.WriteSyncer {
	//引入第三方库 Lumberjack 加入日志切割功能
	lumberWriteSyncer := &lumberjack.Logger{
		Filename:   "./zaplogs/error.log",
		MaxSize:    10, // megabytes
		MaxBackups: 100,
		MaxAge:     28,    // days
		Compress:   false, //Compress确定是否应该使用gzip压缩已旋转的日志文件。默认值是不执行压缩。
	}
	return zapcore.AddSync(lumberWriteSyncer)
}

func InitDB() *gorm.DB {
	dsn := "root:root@tcp(localhost:3306)/beijing_trip?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}
	return db
}
